package com.cy.pj.common.aspect;

import com.cy.pj.common.annotation.RequiredLog;
import com.cy.pj.common.util.IPUtils;
import com.cy.pj.sys.pojo.SysLog;
import com.cy.pj.sys.service.SysLogService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;

@Aspect
@Slf4j
@Component
public class SysLogAspect {
    private final Logger log = LoggerFactory.getLogger(SysLogAspect.class);

    @Pointcut("@annotation(com.cy.pj.common.annotation.RequiredLog)")
    public void doLogPointCut() {}  //别名

    @Around("doLogPointCut()")
    public Object around(ProceedingJoinPoint jp) throws Throwable{
        try {
            long t1 = System.currentTimeMillis();
            log.info("start:{}"+System.currentTimeMillis());
            Object result=jp.proceed();//最终会调用目标方法，其返回值为目标方法的返回值
            long t2 = System.currentTimeMillis();
            log.info("after:{}"+System.currentTimeMillis());
            System.out.println("time"+(t2-t1));
            //将正常用户行为日志写入数据库
            saveSysLog(jp,(t2-t1));

            return result;
        }catch(Throwable e) {
            //在这个位置可以记录，也可以将错误信息写入到数据库或者文件
            //log.error("afte->{}->{}->{}",e.getMessage());
            logError(jp, e.getMessage());
            throw e;
        }
    }
    private void logError(ProceedingJoinPoint jp, String exceptionMsg) throws JsonProcessingException {
        String targetClassName = jp.getTarget().getClass().getName();
        String methodName = jp.getSignature().getName();
        String params = new ObjectMapper().writeValueAsString(jp.getArgs());

        log.error("error.msg->{}->{}->{}",targetClassName+"==="+methodName+"==="+"params",exceptionMsg);
    }

    @Autowired
    private SysLogService sysLogService;
    private void saveSysLog(ProceedingJoinPoint jp,long time) throws NoSuchMethodException, JsonProcessingException {
        //1.获取用户行为
        Class<?> targetClass = jp.getTarget().getClass();
        MethodSignature ms= (MethodSignature) jp.getSignature();
        //获取
        Method targetMethod =targetClass.getDeclaredMethod(ms.getName(),ms.getParameterTypes());
        RequiredLog requiredLog = targetMethod.getAnnotation(RequiredLog.class);
        //获取操作名
        String operation = requiredLog.value();

        //2.封装日志信息
        SysLog entity = new SysLog();
        entity.setUsername("cgb");
        entity.setIp(IPUtils.getIpAddr());  //http://192.168.43.219/doIndexUI

        entity.setOperation(operation); //为目标方法指定一个
        entity.setMethod(targetClass.getName()+"."+targetMethod.getName());
        //entity.setParams(Arrays.toString(jp.getArgs()));
        entity.setParams(new ObjectMapper().writeValueAsString(jp.getArgs()));
        entity.setTime(time);
        entity.setCreatedTime(new Date());
        //3.保存用户行为值
        new Thread(){
            @Override
            public void run() {
                sysLogService.saveObject(entity);
            }
        }.start();


    }
}
